package com.example.CollaborativeDiscussionLearning.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.example.CollaborativeDiscussionLearning.dto.ChatUserDTO;
import com.example.CollaborativeDiscussionLearning.entity.*;
import com.example.CollaborativeDiscussionLearning.handle.sentinelHandler.MyBlockException;
import com.example.CollaborativeDiscussionLearning.handle.sentinelHandler.MyFallback;
import com.example.CollaborativeDiscussionLearning.A.ChatRoomMapping;
import com.example.CollaborativeDiscussionLearning.service.CourseStudentService.CourseStudentService;
import com.example.CollaborativeDiscussionLearning.service.chatRoomService.ChatRoomServiceImpl;
import com.example.CollaborativeDiscussionLearning.service.courseService.CourseService;
import com.example.CollaborativeDiscussionLearning.service.loginAndRegisterService.LoginAndRegisterServiceImpl;
import com.example.CollaborativeDiscussionLearning.vo.DisAnalysisVo;
import com.example.CollaborativeDiscussionLearning.vo.ResponseDataVO;
import com.github.pagehelper.PageInfo;
import com.kennycason.kumo.CollisionMode;
import com.kennycason.kumo.WordCloud;
import com.kennycason.kumo.WordFrequency;
import com.kennycason.kumo.bg.PixelBoundryBackground;
import com.kennycason.kumo.font.scale.LinearFontScalar;
import com.kennycason.kumo.nlp.FrequencyAnalyzer;
import com.kennycason.kumo.palette.ColorPalette;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.UriUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Pattern;
import java.awt.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * @Description: 聊天室控制层
 */
@Slf4j
@Controller
@Validated
public class ChatRoomController {

    @Autowired
    private ChatRoomServiceImpl chatRoomService;

    @Autowired
    private LoginAndRegisterServiceImpl loginAndRegisterService;

    @Autowired
    private CourseService courseService;

    @Autowired
    private CourseStudentService courseStudentService;
    /**
     * 登录页
     * */
    @GetMapping("/loginPage")
    public ModelAndView loginPage() {
        return new ModelAndView("login");
    }
    /**
     * 管理员页面
     * */
    @GetMapping("/Admin")
    public ModelAndView AdminPage() {
        return new ModelAndView("manager");
    }

    /**
     * 分析页面
     * */
    @GetMapping("/teacher")
    public ModelAndView teacherPage() {
        return new ModelAndView("teacher");
    }
    /**
     * 分析页面
     * */
    @GetMapping("/analysis")
    public ModelAndView analysisPage() {
        return new ModelAndView("analysis");
    }
    /**
     * 登录接口
     * */
    @PostMapping("/login")
    @ResponseBody
    public ResponseDataVO login(HttpServletRequest request, HttpServletResponse response, @RequestParam @Pattern(regexp = "^[0-9]{10}$") String code, @RequestParam @Pattern(regexp = "^[a-zA-Z0-9]{8,}$") String password) throws IOException {
        return loginAndRegisterService.login(request, response, code, password);
    }
    /**
     * 注册接口
     * */
    @PostMapping("/register")
    @ResponseBody
    public ResponseDataVO register(@RequestParam @Length(min = 1, max = 10) String name, @RequestParam @Pattern(regexp = "^[0-9]{10}$") String code, @RequestParam String role) {
        return loginAndRegisterService.register(name, code, role);
    }

    /**
     * 首页
     * */
    @GetMapping("/")
    @SentinelResource(value = "index", defaultFallback = "allFallback", fallbackClass = {MyFallback.class},
            blockHandler = "blackException", blockHandlerClass = {MyBlockException.class})
    public ModelAndView index() {
        return new ModelAndView("index");
    }

    /**
     * 获取用户信息 获取用户相关的讨论室
     * */
    @PostMapping("/getUserInfo")
    @ResponseBody
    public ResponseDataVO getUserInfo(HttpServletRequest request) {
        return chatRoomService.getUserInfo(loginAndRegisterService.jwtInfo(request));
    }

    /**
     * 查询用户接口
     * */
    @PostMapping("/queryUser")
    @ResponseBody
    public ResponseDataVO queryUsers(@RequestParam @Length(min = 1, max = 10) String name, @RequestParam @Pattern(regexp = "^[0-9]{10}$")String code) {
        ChatUserDTO newUserDTO = ChatUserDTO.builder()
                .name(name)
                .code(code)
                .build();
        ChatUser user = ChatRoomMapping.INSTANCE.chatUserDTOToChatUser(newUserDTO);
        ChatUser queryUser = chatRoomService.queryUser(user);
        if(queryUser!=null){
            return ResponseDataVO.success(queryUser);
        }else{
            return ResponseDataVO.fail(201,"查询的用户不存在");
        }
    }

    /**
     * 删除用户接口
     * */
    @PostMapping("/deleteUser")
    @ResponseBody
    public ResponseDataVO deleteUser(@RequestParam @Length(min = 1, max = 10) String name, @RequestParam  @Pattern(regexp = "^[0-9]{10}$") String code) {
        ChatUserDTO newUserDTO = ChatUserDTO.builder()
                .name(name)
                .code(code)
                .build();
        log.info("_______________________________"+name);
        log.info(newUserDTO.toString());
        ChatUser user = ChatRoomMapping.INSTANCE.chatUserDTOToChatUser(newUserDTO);
        int res = chatRoomService.deleteUser(user);
        if(res == 1){
            return ResponseDataVO.success("删除成功");
        }else{
            return ResponseDataVO.fail(201,"删除的用户不存在");
        }
    }

    /**
     * 添加讨论室 先获取该用户相关的讨论室，再建新的讨论室内
     * */
    @PostMapping("/addChat")
    @ResponseBody
    public ResponseDataVO addChat(HttpServletRequest request, @RequestParam @Length(min = 3, max = 12) String  roomName,@RequestParam String item,@RequestParam String content,@RequestParam String key) {
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();
        return chatRoomService.insertChatRoom(roomName,code,item,content,key);
    }

    /**
     * 添加讨论室 先获取该用户相关的讨论室，再建新的讨论室内
     * */
    @PostMapping("/insertUserRoom")
    @ResponseBody
    public ResponseDataVO insertUserRoom(HttpServletRequest request,@RequestParam Integer roomId) {
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();
        UserRoom userRoom = UserRoom.builder().userCode(code).roomId(roomId).build();
        chatRoomService.insertUserRoom(userRoom);
        return ResponseDataVO.success("添加学生-讨论室信息成功");
    }


    /**
     * 查询学生-课程关系，检测讨论室是否存在
     * */
    @PostMapping("/checkCourseStudent")
    @ResponseBody
    public ResponseDataVO checkCourseStudent(HttpServletRequest request, @RequestParam @Length(min = 3, max = 12) String  roomName, @RequestParam String course, @RequestParam String teacher) {
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();
        //先检测该课程是否存在
        Course course1 = new Course().setTeacher(teacher).setName(course);
        Course exitCourse = courseService.query(course1);
        log.info(exitCourse.toString());
        if(exitCourse != null){
            //检测该该学生-课程信息是否存在
            CourseStudent courseStudent = new CourseStudent().setStudentCode(code).setCourseCode(exitCourse.getId());
            CourseStudent exitCourseStudent = courseStudentService.queryCourseStudent(courseStudent);
           log.info(exitCourseStudent.toString());
            if(exitCourseStudent!=null){
                //检测房间是否存在
                // 查询房间是否存在
                ChatRoom queryChatRoom = chatRoomService.queryRoomByRoomNameAndCourseId(roomName, exitCourse.getId());
                log.info(queryChatRoom.toString());
                if(queryChatRoom != null){
                    //检测是否已经存在用户和房间关联
                    // 查询当前房间是否和用户邮箱绑定
                    UserRoom queryUserRoom = chatRoomService.queryUserRoom(code, queryChatRoom.getRoomId());
                    log.info(queryUserRoom.toString());
                    if(queryUserRoom!=null){
                        return ResponseDataVO.fail("用户已经加入该讨论室！");
                    }else if(exitCourse.getId()==1){
                        return ResponseDataVO.fail("公共讨论室不许重新加入！");
                    }else{
                        // 用户邮箱和房间号绑定
                        UserRoom userRoom = UserRoom.builder()
                                .userCode(code)
                                .roomId(queryChatRoom.getRoomId())
                                .createTime(LocalDateTime.now())
                                .build();
                        log.info(userRoom.toString());
                        return ResponseDataVO.success(userRoom);
                    }
                }else{
                    return ResponseDataVO.fail(201,"该讨论室不存在！");
                }
            }else{
                return ResponseDataVO.fail("该房间不存在！");
            }
        }else {
            return ResponseDataVO.fail("该房间不存在！");
        }
    }

    /**
     * 修改用户密码
     * */
    @PostMapping("/revise")
    @ResponseBody
    public ResponseDataVO revisePassage(@RequestParam @Pattern(regexp = "^[0-9]{10}$") String code, @RequestParam @Pattern(regexp = "^[a-zA-Z0-9]{8,}$") String password) {
        Integer res=chatRoomService.revisePassWord(code,password);
        if(res==0) {
            return ResponseDataVO.fail("修改失败");
        }else{
            return ResponseDataVO.success("修改密码成功");
        }
    }

    /**
     * 查询讨论室的基本信息
     * */
    @RequestMapping("/selectChatRoom")
    @ResponseBody
    public ResponseDataVO selectChatRoom(@RequestParam String chatName){
        ChatRoom chatRoomFind = chatRoomService.queryRoomByRoomName(chatName);
        if(chatRoomFind==null){
            return ResponseDataVO.fail("找不到对应的房间");
        }else {
            log.info(chatRoomFind.toString());
            return ResponseDataVO.success(chatRoomFind);
        }
    }


    /**
     * 查询讨论室的所有成员信息
     * */
    @RequestMapping("/selectChatRoomUser")
    @ResponseBody
    public ResponseDataVO selectChatRoomUser(@RequestParam String chatName){
        ChatRoom chatRoomFind = chatRoomService.queryRoomByRoomName(chatName);
        if(chatRoomFind!=null){
            List<ChatUser> chatUserList =chatRoomService.selectByRoomIdForUsers(chatRoomFind.getRoomId());
            if(chatUserList!=null){
               return ResponseDataVO.success(chatUserList);
            }else{
                return ResponseDataVO.fail("该讨论室未有用户");
            }
        }else{
            return ResponseDataVO.fail("该讨论室不存在");
        }
    }

    /**
     * 删除讨论室
     * */
    @PostMapping("/delChat")
    @ResponseBody
    public ResponseDataVO delChat(HttpServletRequest request, @RequestParam String roomName) throws IOException {
        //获取用户信息
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();
        return chatRoomService.deleteUserRoom(roomName, code);
    }

    /**
     *
     * 生成点云图片
     * */

    public void wordCloud() throws IOException {
        final FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer();
        frequencyAnalyzer.setWordFrequenciesToReturn(300);
        frequencyAnalyzer.setMinWordLength(4);
        frequencyAnalyzer.setStopWords(loadStopWords());

        final List<WordFrequency> wordFrequencies = frequencyAnalyzer.load("D:\\A_project\\new_chat\\multi-person-chat-room\\src\\main\\resources\\text\\datarank.txt");
        final Dimension dimension = new Dimension(500, 312);
        final WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT);
        wordCloud.setPadding(2);
        wordCloud.setBackground(new PixelBoundryBackground("D:\\A_project\\new_chat\\multi-person-chat-room\\src\\main\\resources\\backgrounds\\whale_small.png"));
        wordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF)));
        wordCloud.setFontScalar(new LinearFontScalar(10, 40));
        wordCloud.build(wordFrequencies);
        wordCloud.writeToFile("D:\\A_project\\new_chat\\multi-person-chat-room\\src\\main\\resources\\output\\whale_wordcloud_small.png");
    }

    private Collection<String> loadStopWords() {
        List<String> strings=new ArrayList<>();
        return strings;
    }

    /**
     * 上传文件
     * */
    @PostMapping("/uploadFile")
    @ResponseBody
    public ResponseDataVO uploadFile(HttpServletRequest request, @RequestParam String roomName,
                                     @RequestParam MultipartFile file, @RequestParam Integer index) throws IOException {
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();

        return chatRoomService.uploadFile(roomName, code, file, index);
    }


    /**
     * 下载文件信息
     * */
    @GetMapping("/download")
    @ResponseBody
    public ResponseEntity<Resource> download(@RequestParam String fileName, @RequestParam String roomName, @RequestParam String alias) throws UnsupportedEncodingException {
        Resource resource = chatRoomService.downloadFile(roomName, fileName);
        String encodedFileName = UriUtils.encodePath(alias, StandardCharsets.UTF_8.toString());

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                .body(resource);
    }

    /**
     * 加载讨论信息
     * */
    @PostMapping("/loadingMsg")
    @ResponseBody
    public ResponseDataVO loadingMsg(HttpServletRequest request, @RequestParam String roomName, @RequestParam Integer pageIndex) {
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String email = chatUserDTO.getCode();
        PageInfo<ChatMsg> pageInfo = chatRoomService.queryMsg(pageIndex, roomName, email);
        log.info("--------------------------------"+pageInfo.toString());
        return ResponseDataVO.success(pageInfo);
    }

    /**
     * 加载问答信息
     * */
    @PostMapping("/loadingAnswer")
    @ResponseBody
    public ResponseDataVO loadingAnswer(HttpServletRequest request, @RequestParam String roomName) {
        List<ChatMsg> chatMsgList = chatRoomService.queryAnswer(roomName);
        return ResponseDataVO.success(chatMsgList);
    }



    /**
     * 触发分析按钮  得到后台开始将聊天信息转换记录信息
     * */
    @PostMapping("/DisAnalysis")
    @ResponseBody
    public ResponseDataVO insertDisAnalysis(HttpServletRequest request, @RequestParam String roomName) {
        //获取用户信息
        log.info("开始加载分析记录");
        ChatUserDTO chatUserDTO = loginAndRegisterService.jwtInfo(request);
        String code = chatUserDTO.getCode();
        //1.根据房间号获取房间信息
        ChatRoom chatRoom = chatRoomService.queryRoomByRoomName(roomName);
        //2.根据房间信息获取该房间所有用户信息
        List<ChatUser> chatUserList = chatRoomService.selectByRoomIdForUsers(chatRoom.getRoomId());
        //排除wenwen的信息
        ChatUser wen = new ChatUser();
        wen.setName("文文");
        wen.setCode("2020213710");
        //查找文文的具体信息
        ChatUser wenChatUser = chatRoomService.queryUserByCode(wen.getCode());
        wen.setId(wenChatUser.getId());
        chatUserList.remove(wen);
        //排除教师的信息
        Integer courseId= chatRoom.getCourseId();
        Course course = courseService.queryById(courseId);
        String teacherCode = course.getTeacherCode();
        ChatUser teacherUser = chatRoomService.queryUserByCode(teacherCode);
        chatUserList.remove(teacherUser);
        //3.根据用户信息和房间信息获取每个用户的记录
        if (!chatUserList.isEmpty()) {
            //获取全部信息记录
            List<ChatMsg> chatMsgList = chatRoomService.queryAllMsg(chatRoom.getRoomId());
            //对信息记录进行分类
            DisAnalysisVo disAnalysisVo = countMsg(chatMsgList,teacherCode,wen.getCode());
            //成员总数
            disAnalysisVo.setStudentCount(chatUserList.size());
            disAnalysisVo.setItem(chatRoom.getItem());
            disAnalysisVo.setContent(chatRoom.getContent());
            disAnalysisVo.setContentKey(chatRoom.getContentKey());
            //开始时间
            /*// 选择一个时区，这里以系统默认时区为例
            ZoneId zoneId = ZoneId.systemDefault();
            // 将LocalDateTime转换为ZonedDateTime
            ZonedDateTime startZonedDateTime = chatMsgList.get(0).getSendTime().atZone(zoneId);
            ZonedDateTime endZonedDateTime = chatMsgList.get(chatMsgList.size()-1).getSendTime().atZone(zoneId);

            Duration duration = Duration.between(startZonedDateTime, endZonedDateTime);
            */
            //String timeCount = duration.toHours()+"h"+duration.toMinutes()+"min";
            String timeCount = "0 h"+" 40 min";
            disAnalysisVo.setDuration(timeCount);
            return ResponseDataVO.success(disAnalysisVo);
        }else{
            return ResponseDataVO.fail("获取统计数据失败");
        }
    }

    public DisAnalysisVo countMsg(List<ChatMsg> chatMsgList,String teacherCode,String wenCode){
        DisAnalysisVo disAnalysisVo = new DisAnalysisVo();
        Integer countMsg=0;
        Integer countQuestions=0;
        Integer countOffTopic=0;
        for(ChatMsg chatMsg : chatMsgList){
            if(chatMsg.getSender().equals(teacherCode) || chatMsg.getSender().equals(wenCode)){
                continue;
            }else{
                if(chatMsg.getMsgType().equals("question")){
                    countQuestions+=1;
                }else if(chatMsg.getMsgType().equals("answer")){
                    //不计数
                }else{
                    countMsg+=1;
                }
            }
        }
        disAnalysisVo.setMsgCount(countMsg);
        disAnalysisVo.setOffTopicCount(countOffTopic);
        disAnalysisVo.setQuestionCount(countQuestions);
        return disAnalysisVo;
    }
}
